let Vue
class VueRouter {
  constructor(options) {
    this.$options = options
    this.routeMap = {}
    this.app = new Vue({
      data() { return { current: '' } }
    })
  }
  init() {
    this.bindEvents()
    this.createRouteMap(this.$options)
    this.initComponents()
  }
  bindEvents() {
    window.addEventListener('hashchange', (event) => {
      this.app.current = location.hash ? location.hash.slice(1) : '/'
    })
    window.addEventListener('DOMContentLoaded', (event) => {
      this.app.current = location.hash ? location.hash.slice(1) : '/'
    })
  }
  createRouteMap({ routes }) {
    routes.forEach(routeRule => this.routerFormat(this.routeMap, routeRule))
  }
  routerFormat(routerMap, routeRule, parentUrl = '') {
    const key = routeRule.path
    const curRouterMap = routerMap[key] = { component: routeRule.component }
    if (routeRule.children) {
      curRouterMap.children = {}
      routeRule.children.forEach(itemRule => this.routerFormat(curRouterMap.children, itemRule))
    }
  }
  initComponents() {
    Vue.component('router-link', {
      props: {
        to: {
          type: String,
          default: ''
        }
      },
      render(h) {
        return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
      }
    })

    let self = this
    Vue.component('router-view', {
      name: 'router-view',
      data() { return { app: self.app } },
      render(h) {
        let parent = this.$parent
        while (parent != this.$root) {
          if (parent.$options._componentTag == 'router-view') {
            break
          }
          parent = parent.$parent
        }
        let routerRule, key, routerParams = {}, paramsKey
        const current = self.app.current
        if (parent == this.$root) {
          key = Object.keys(self.routeMap).find(path => {
            const pathArr = path.slice(1).split('/')
            const currentArr = current.slice(1).split('/').slice(0, pathArr.length)
            return pathArr.every((val, i) => {
              if (val.includes(':')) {
                routerParams[val.slice(1)] = currentArr[i]
                return true
              } else if (val == currentArr[i]) {
                return true
              }
            })
          })
          routerRule = self.routeMap[key]
          if (routerRule) {
            paramsKey = Object.keys(routerParams)[0]
            if (paramsKey) {
              this.matchedUrl = key.replace(':' + paramsKey, routerParams[paramsKey])
            } else {
              this.matchedUrl = key
            }
          }
        } else {
          key = Object.keys(parent.childRouteMap).find(path => {
            const pathArr = path.slice(1).split('/')
            const currentArr = current.replace(parent.matchedUrl, '').slice(1).split('/').slice(0, pathArr.length)
            return pathArr.every((val, i) => {
              if (val.includes(':')) {
                routerParams[val.slice(1)] = currentArr[i]
                return true
              } else if (val == currentArr[i]) {
                return true
              }
            })
          })
          routerRule = parent.childRouteMap[key]
          if (routerRule) {
            paramsKey = getFirstKey(routerParams)
            if (paramsKey) {
              this.matchedUrl = parent.matchedUrl + key.replace(':' + paramsKey, routerParams[paramsKey])
            } else {
              this.matchedUrl = parent.matchedUrl + key
            }
          }
        }
        // console.log(routerParams)
        // console.log(routerRule)
        if (routerRule) {
          this.childRouteMap = routerRule.children ? routerRule.children : ''
          if (routerRule.component) {
            if (paramsKey) {
              return h(routerRule.component, { props: { ...routerParams } })
            } else {
              return h(routerRule.component)
            }
          }
        }
      },
    })
  }
}

VueRouter.install = function (_vue) {
  Vue = _vue
  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {
        Vue.prototype.$router = this.$options.router;
        this.$options.router.init()
      }
    }
  })
}

function getFirstKey(obj) {
  const firstKey = Object.keys(obj)[0]
  return firstKey ? firstKey : false
}

export default VueRouter